package com.gitee.wsl.common.ui.ext

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.Matrix
import androidx.compose.ui.graphics.isIdentity
import com.gitee.wsl.common.ui.base.Point
import kotlin.math.PI
import kotlin.math.absoluteValue
import kotlin.math.atan2

enum class ScaleToFit {
    FILL,
    START,
    CENTER,
    END
}


fun Matrix.setRectToRect(srcBox:Rect,dstBox:Rect,type:ScaleToFit = ScaleToFit.CENTER){

}


 val Matrix.translateX get() = values[Matrix.TranslateX]
 val Matrix.translateY get() = values[Matrix.TranslateY]

 val Matrix.scaleX get() = values[Matrix.ScaleX]
 val Matrix.scaleY get() = values[Matrix.ScaleY]

 val Matrix.skewX get() = values[Matrix.SkewX]
 val Matrix.skewY get() = values[Matrix.SkewY]

 val Matrix.persp0 get() = values[Matrix.Perspective0]
 val Matrix.persp1 get() = values[Matrix.Perspective1]
 val Matrix.persp2 get() = values[Matrix.Perspective2]

fun Matrix.map(sx: Float, sy: Float): Point = map(Point(sx , sy))

fun Point.matrix(matrix: Matrix) = matrix.map(this)

fun Matrix.println(): String {
    val elements = mutableListOf<String>()
    if (translateX != 0f || translateY != 0f) {
        elements += "translate($translateX, $translateY)"
    }

    if (scaleX != 1f || scaleY != 1f) {
        elements += "scale($scaleX, $scaleY)"
    }

    if (skewX != 0f || skewY != 0f) {
        elements += "skew($skewX, $skewY)"
    }

    if (elements.isEmpty()) {
        return "identity"
    }

    return elements.joinToString(separator = " ")
}


/**
 * Creates a rotation transformation matrix based on two given points.
 *
 * @param firstPoint The first reference point.
 * @param lastPoint The second point used to determine the rotation angle.
 * @return A transformation matrix with applied rotation and translation based on the given points.
 */

fun Matrix.Companion.rotateMatrix(firstPoint: Offset, lastPoint: Offset): Matrix {
    val matrix = Matrix()

    val deltaX = lastPoint.x - firstPoint.x
    val deltaY = lastPoint.y - firstPoint.y

    val angleRad = atan2(deltaY, deltaX)
    val angle = angleRad * (180 / PI)

    matrix.rotateZ(angle.toFloat())
    matrix.translate(
        x = -firstPoint.x,
        y = -firstPoint.y,
    )

    return matrix
}

fun Matrix.fastSetFrom(other : Matrix){
    other.values.copyInto(values)
}

internal fun Matrix.setValues(values : FloatArray){
    this.values[Matrix.ScaleX] = values[0]
    this.values[Matrix.SkewX] = values[1]
    this.values[Matrix.TranslateX] = values[2]
    this.values[Matrix.SkewY] = values[3]
    this.values[Matrix.ScaleY] = values[4]
    this.values[Matrix.TranslateY] = values[5]
    this.values[Matrix.Perspective0] = values[6]
    this.values[Matrix.Perspective1] = values[7]
    this.values[Matrix.Perspective2] = values[8]
}

fun Matrix.preConcat(other : Matrix) {

    if (other.isIdentity()) {
        return
    }

    if (isIdentity()){
        fastSetFrom(other)
        return
    }

    val tempMatrixConcat = Matrix()
    tempMatrixConcat.fastSetFrom(other)
    tempMatrixConcat.timesAssign(this)
    fastSetFrom(tempMatrixConcat)

//    timesAssign(other)
}

internal val IdentityMatrix = Matrix()

fun Matrix.fastReset() {
    fastSetFrom(IdentityMatrix)
}


internal fun Matrix.preRotate(degree : Float) {
    if (degree.absoluteValue < Float.MIN_VALUE) {
        return
    }
//    preConcat(tempMatrixTransform.apply {
//        fastReset()
//        rotateZ(degree)
//    })
//
    return rotateZ(degree)
}

private val tempMatrixTransform = Matrix()

internal fun Matrix.preRotateX(degree : Float) {
    if (degree.absoluteValue < Float.MIN_VALUE) {
        return
    }
    preConcat(tempMatrixTransform.apply {
        fastReset()
        rotateX(degree)
    })
}

internal fun Matrix.preRotateY(degree : Float) {
    if (degree.absoluteValue < Float.MIN_VALUE) {
        return
    }
    preConcat(tempMatrixTransform.apply {
        fastReset()
        rotateY(degree)
    })
}
internal fun Matrix.preRotateZ(degree : Float) {
    if (degree.absoluteValue < Float.MIN_VALUE) {
        return
    }
    preConcat(tempMatrixTransform.apply {
        fastReset()
        rotateZ(degree)
    })
}

